Lesson 5

In this lesson, we will use the find_position function from the previous lesson to implement a one-dimensional version of piTap. You can tap anywhere along a line and have the program predict where you've tapped!

Copy and paste your find position function into the program block below.


In [1]:
#find_position here
def find_position(a, t, s):
    return (a-s*t)/2.0;

Take a brief moment to review what it does. It takes in three parameters, $a$ (position of friend's house), $t$ (time distance of arrival), and $s$ (the speed you and your friend travel at). Now instead of using the metaphor of you and your friend racing home, how can this be used to model the piTap?

The setup of piTap is that there are two sensors, connected by a horizontal line. We want to be able to tap anywhere in between the line and predict where we've tapped. This is similar to you and your friend running home, except now it is two waves that are racing towards the sensors. The sensors are analogous to the homes, the position of the tap is is analogous to the location of the hangout spot, and the circular wave front is equivalent to you and your friend running left and right.

We know what the value of $a$ is, just the distance beween the two sensors, which we can measure with a meter stick or ruler. We know what $t$ is since we can ask the raspberry Pi what the time difference between the sensors is. However, we do not yet know what $s$ is, and we will need some way of calculating it. From the previous lesson, we asked "What is the TDOA if you decide to hang out at a location LEFT of your house?". The answer to this is that it is simply the the time it takes your friend to run to his house from your house. Thus if we tap the board LEFT of the leftmost sensor, the time distance of arrival will be the time it takes the wave to propagate from one sensor to another. And since we know that the distance between the sensors, we can use the formula that $s = \frac{\Delta p}{t} = \frac{a}{t}$.

So we could calculate $s$ by tapping the board left of the left-most sensor, retrieve the TDOA and take the quotient of the length and the TDOA. However, since we've only conducted the experiment once, this result could be rather inaccurate. In order to get a more accurate value of $s$, we will want to conduct this experiment multiple times and then take an average of all the experiment results.

Below, write a program that creates an initialliy empty list called "speeds" that will eventually contain ten values of the $s$, calculated in ten different trials. Use a while loop to wait for ten time differences, calculate the speed for that trial and then appends it to speeds.

Initialize $a$ at the very beginning to be the length of the distance between the two sensors (which you should measure with a ruler). Finally, run the code block and tap LEFT of the left-most sensor ten times.


In [10]:
#WRITE YOUR CODE HERE
#ANSWER
a = 1.0
speeds = []
i = 10
while(i > 0):
    i = i-1
    thisTime = 1 #piTap.getTDOA()
    speeds.append(a/thisTime)


[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

Finally, we want to calculate the average of all the values in speeds. Do this by calculating the sum of all the values in speeds, then dividing it by ten (the number of elements in speeds). Set $s$ to be this value.


In [12]:
#WRITE YOUR CODE HERE
s = 0
for newS in speeds:
    s = s + newS
s = s/10
print s


1.0

Now we know $a$ and $s$! So whenever we get a $t$ by tapping the board, we should be able to calculate the position of where we've tapped!

We've written the majority of the meat for our code. However, displaying a texual format of where we've tapped isn't so satisfying. We want something visual and exciting! So instead of just printing out where we tapped, we move our mouse to the location. The effect of this is that when we project our screen onto the board, we can set the sensors to be at the left most edge and right most edge. Whenever we tap on the line in between them, our mouse will travel to where we've tapped, creating a tocuh screen!

Writing a module that will move our mouse from scratch is rather difficult, however, someone else has done this already! The library that moves the mouse is called PyMouse. We can import this library by calling

from pymouse import PyMouse

Do this in the code block below.


In [2]:
#from pymouse import PyMouse 
import time

Now we can use this to make our mouse move to any pixel on the screen. We will first need to write a method that clicks to a position $(x,y)$. The way coordinates are defined here are not quite the same as cartesian coordinates. The upper left corner is defined as $(0,0)$. Increasing the first coordinate still makes the mouse move right, but increasing the second coordinate will make the mouse move down.

Run the code below to see what I mean


In [ ]:
mouse = PyMouse() #Making a new mouse
mouse.move(0,0) #Making the mouse move to the very top left corner
time.sleep(1)
mouse.move(10, 0) #Moving the mouse right
time.sleep(1)
mouse.move(20, 0)
time.sleep(1)
mouse.move(30, 0)
time.sleep(1)
mouse.move(30, 10)
time.sleep(1)
mouse.move(30, 20)
time.sleep(1)
mouse.move(30, 30)

We will now need to find the resolution of our monitor. The resolution tells us the dimensions of our display, pixels wide by pixels tall.

This is done for you below. Run the code below.


In [7]:
import Tkinter as tk
root = tk.Tk()

widthPixels = root.winfo_screenwidth()
heightPixels = root.winfo_screenheight()

print (widthPixels, heightPixels)


(1280, 800)

We will want to have the line where we can tap be the halfway point between the top of the projected screen and the bottom of the projected screen. Thus the $y$ coordinate of our mouse will always be at the number of pixels tall our screen is divided by 2.

But now we need to figure out how far along the $x-axis$ we will go, we can do this with ratios. $\frac{find_{}-position}{a} = \frac{x-coordinate}{width}$, discuss why this is true. We then know that x-coordinate $= \frac{find_-position}{a}*widthPixels$

Implement a function below that given the $a$, the width of the projection, $t$, a time distance of arrival, and $s$, the speed of a wave in the board, moves the mouse to the corresponding location on screen. Call it tap.


In [11]:
#Write your function here.

#Solution

def tap(a, t, s):
    x_coordinate = (find_position(a,t,s)/a)*widthPixels
    y_coordinate = heightPixels/2
    mouse.move(x_coordinate, y_coordinate)

This completes the one-dimensional PiTap! Below we've written some code that runs this method every time you tap on the board. So everytime you tap on the board, we read a time difference. We've set the constants $a$ and $s$ already, so we can just call tap(a,t,s) with the new time difference, and our mouse will automatically move to where we'ved tapped! Run the codeblock below and tap on the board. Sometimes the mouse does not go exactly to where you've tapped, this is because of error/noise in the signals, but it should be pretty close!


In [13]:
#import boardControlLib
#b = boardControlLib.BoardControl()

while(False):
    tap(a, b.getTime(), s)
    time.sleep(.05)

Notice that from the last lab we have determined that the amplitude of the wvae and the velocity of the wave in the medium are independant from each other. This means that if you tap the board harder, the waves won't travel any faster, and the prediction methods will still be valid.


In [ ]: